package com.hudson.codec.domain;

import com.hudson.codec.hudson.utils.CodecUtil;
import io.netty.buffer.ByteBuf;

import java.util.Arrays;
import java.util.Map;

public class RemotingCommand {
    private String type;
    private long opaque;
    private String remark;
    private Map<String, String> extFields;
    private byte[] body;

    // 私有构造函数，只能通过构建器创建
    private RemotingCommand(Builder builder) {
        this.type = builder.type;
        this.opaque = builder.opaque;
        this.remark = builder.remark;
        this.extFields = builder.extFields;
        this.body = builder.body;
    }

    public RemotingCommand(String type, long opaque, String remark, Map<String, String> extFields, byte[] body) {
        this.type = type;
        this.opaque = opaque;
        this.remark = remark;
        this.extFields = extFields;
        this.body = body;
    }

    public RemotingCommand() {
    }

    public String getType() {
        return type;
    }

    public long getOpaque() {
        return opaque;
    }

    public String getRemark() {
        return remark;
    }

    public Map<String, String> getExtFields() {
        return extFields;
    }

    public byte[] getBody() {
        return body;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setOpaque(long opaque) {
        this.opaque = opaque;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public void setExtFields(Map<String, String> extFields) {
        this.extFields = extFields;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    // 静态 builder 方法
    public static Builder builder() {
        return new Builder();
    }

    // 构建器内部类
    public static class Builder {
        private String type;
        private long opaque;
        private String remark;
        private Map<String, String> extFields;
        private byte[] body;

        private Builder() {
        }

        public Builder type(String type) {
            this.type = type;
            return this;
        }

        public Builder opaque(long opaque) {
            this.opaque = opaque;
            return this;
        }

        public Builder remark(String remark) {
            this.remark = remark;
            return this;
        }

        public Builder extFields(Map<String, String> extFields) {
            this.extFields = extFields;
            return this;
        }

        public Builder body(byte[] body) {
            this.body = body;
            return this;
        }

        // build 方法创建不可变对象
        public RemotingCommand build() {
            return new RemotingCommand(this);
        }
    }

    @Override
    public String toString() {
        return "RemotingCommand{" +
                "type='" + type + '\'' +
                ", opaque=" + opaque +
                ", remark='" + remark + '\'' +
                ", extFields=" + extFields +
                ", body=" + Arrays.toString(body) +
                '}';
    }

    public static void serialize(RemotingCommand command, ByteBuf out) {
        // 序列化type字段
        CodecUtil.writeString(out, command.getType());

        // 序列化opaque字段
        out.writeLong(command.getOpaque());

        // 序列化remark字段
        CodecUtil.writeString(out, command.getRemark());

        // 序列化extFields字段
        Map<String, String> extFields = command.getExtFields();
        CodecUtil.writeExtData(out, command.extFields);

        // 序列化body字段
        byte[] body = command.getBody();
        if (body == null) {
            out.writeInt(0);
        } else {
            out.writeInt(body.length);
            out.writeBytes(body);
        }
    }

    /**
     * 从ByteBuf反序列化RemotingCommand
     */
    public static RemotingCommand deserialize(ByteBuf in) {
        RemotingCommand command = new RemotingCommand();

        // 反序列化type字段
        command.setType(CodecUtil.readString(in));

        // 反序列化opaque字段
        command.setOpaque(in.readLong());

        // 反序列化remark字段
        command.setRemark(CodecUtil.readString(in));

        // 反序列化extFields字段

        command.setExtFields(CodecUtil.readExtData(in));

        // 反序列化body字段
        int bodyLength = in.readInt();
        if (bodyLength > 0) {
            byte[] body = new byte[bodyLength];
            in.readBytes(body);
            command.setBody(body);
        }

        return command;
    }


}
